package com.jpa;

import javax.swing.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;


public class MainFrame extends JFrame {
    //准备数组，用于存储数字色块的位置行列位置
    private int[][] imageData = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };
    private final int[][] WIN_DATA = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };
    //用常量存储模块位置
    private static final String imagePath = "stone-maze/src/image/";
    //定义两个整数，用于记录空白图片的位置
    //blankRow,blankCol
    private int blankRow;
    private int blankCol;


    //自定义窗口类
    public MainFrame() {
        //1.调用初始化方法，初始化窗口
        initFrame();
        //4.打乱数字色块的顺序
        initRandomArray();
        //2.初始化界面，展示数字色块
        initImage();
        //3.初始化系统菜单，点击系统菜单弹出，系统退出，重启游戏
        initMenu();
        //5.给当前窗口绑定上下左右案件事件
        initKeyPressEvent();

        this.setVisible(true);
    }

    private void initKeyPressEvent() {
        //给当前窗口绑定上下左右案件事件
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //获取当前按键的编码
                int keyCode = e.getKeyCode();
                //判断按键编码，上下左右
                switch (keyCode) {
                    //上
                    case KeyEvent.VK_UP:
                        switchAndMove(Direction.UP);
                        break;
                    //下
                    case KeyEvent.VK_DOWN:
                        switchAndMove(Direction.DOWN);
                        break;
                    //左
                    case KeyEvent.VK_LEFT:
                        switchAndMove(Direction.LEFT);
                        break;
                    //右
                    case KeyEvent.VK_RIGHT:
                        switchAndMove(Direction.RIGHT);
                        break;
                }
            }
        });
    }

    private void switchAndMove(Direction direction) {
        //判断图片的方向，再对图片移动
        switch (direction) {
            case UP:
                //上交换行必须小于三，然后才能交换
                if(blankRow<3){
                    //当前色块的位置 rol ,col
                    //需要交换的位置row+1,col
                    int temp = imageData[blankRow][blankCol];
                    imageData[blankRow][blankCol] = imageData[blankRow+1][blankCol];
                    imageData[blankRow+1][blankCol] = temp;
                    //更新空白图片的位置
                    blankRow++;
                }
                break;
            case DOWN:
                //下交换行必须大于0，然后才能交换
                if(blankRow>0){
                    //当前色块的位置 rol ,col
                    //需要交换的位置row-1,col
                    int temp = imageData[blankRow][blankCol];
                    imageData[blankRow][blankCol] = imageData[blankRow-1][blankCol];
                    imageData[blankRow-1][blankCol] = temp;
                    //更新空白图片的位置
                    blankRow--;
                }
                break;
            case LEFT:
                //左交换空白色块的列小于三，然后才能交换
                if(blankCol<3){
                    //当前色块的位置 rol ,col
                    //需要交换的位置row,col+1
                    int temp = imageData[blankRow][blankCol];
                    imageData[blankRow][blankCol] = imageData[blankRow][blankCol+1];
                    imageData[blankRow][blankCol+1] = temp;
                    //更新空白图片的位置
                    blankCol++;
                }
                break;
            case RIGHT:
                //右交换空白色块的列必须大于0，然后才能交换
                if(blankCol>0){
                    //当前色块的位置 rol ,col
                    //需要交换的位置row,col-1
                    int temp = imageData[blankRow][blankCol];
                    imageData[blankRow][blankCol] = imageData[blankRow][blankCol-1];
                    imageData[blankRow][blankCol-1] = temp;
                    //更新空白图片的位置
                    blankCol--;
                 }
                break;
        }

        initImage();
    }


    private void initRandomArray() {
        //打乱二维数组中的元素顺序
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                //随机两个位置，让两个位置交换
                int i1 = (int) (Math.random() * 4);
                int j1 = (int) (Math.random() * 4);

                int i2 = (int) (Math.random() * 4);
                int j2 = (int) (Math.random() * 4);

                int temp = imageData[i1][j1];
                imageData[i1][j1] = imageData[i2][j2];
                imageData[i2][j2] = temp;
            }
        }
        //定位空白色块的位置
        //去二维数组中找到0
        Out:
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                if (imageData[i][j] == 0) {
                    //记录空白图片的位置
                    blankRow = i;
                    blankCol = j;
                    break Out;
                }
            }
        }
    }

    private void initMenu() {
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("系统");
        JMenuItem exitItem = new JMenuItem("退出");
        menu.add(exitItem);
        exitItem.addActionListener(e -> {
            dispose();
        });
        //添加一个菜单重启
        JMenuItem restartItem = new JMenuItem("重启游戏");
        menu.add(restartItem);
        restartItem.addActionListener(e -> {
            initRandomArray();
            initImage();
        });
        //添加菜单到菜单栏中
        menuBar.add(menu);
        this.setJMenuBar(menuBar);
    }

    private void initImage() {
        //先清空窗口
        this.getContentPane().removeAll();

        //判断游戏是否胜利
        if(isWin()){
            //展示胜利图片
            JLabel label = new JLabel(new ImageIcon(imagePath + "win.png"));
            label.setBounds(124, 230, 266, 88);
            this.add(label);
        }
        //1.展示一个行列矩阵的图片色块依次铺满窗口(4*4)
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                //2.创建一个Jlabel对象，设置图片，设置位置，添加到窗口中
                String imageName = imageData[i][j] + ".png";

                JLabel label = new JLabel();
                //3.设置图片到label中
                label.setIcon(new ImageIcon(imagePath + imageName));
                //4.设置位置
                label.setBounds(22 + j * 100, 60 + i * 100, 100, 100);
                //5.把图片展示到窗口中去
                this.add(label);
            }
        }
        //设置窗口背景图片
        JLabel background = new JLabel(new ImageIcon(imagePath + "background.png"));
        background.setBounds(0, 0, 450, 484);
        this.add(background);

        //在刷新图层，重新绘制
        this.repaint();
    }

    private boolean isWin() {
        //判断是否胜利，遍历二维数组，判断每个元素是否和win数组的对应元素相等，如果相等，继续遍历，直到遍历完，返回true，否则返回false
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                if (imageData[i][j] != WIN_DATA[i][j]) {
                    return false;
                }
            }
        }
        //遍历完，返回true
        return true;
    }

    public void initFrame() {
        //窗口标题
        this.setTitle("石子迷阵v1.0");
        //窗口大小
        this.setSize(465, 575);
        //设置窗口剧中显示
        this.setLocationRelativeTo(null);
        //设窗口绝对布局
        this.setLayout(null);
        //窗口关闭方式
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //窗口可见
    }
}
